package com.packagetracker.providers;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import com.packagetracker.entities.Settings;

public class TrackerProvider extends ContentProvider {
	
	private SQLiteDatabase database;
	private static final String LOG = "SettingsProvider";
	
	private class DatabaseHelper extends SQLiteOpenHelper {
		DatabaseHelper(final Context context) {
			super(context, TrackerProviderSetup.DATABASE_NAME, null, TrackerProviderSetup.DATABASE_VERSION);
		}
		
		@Override
		public void onCreate(final SQLiteDatabase database) {
			TrackerProvider.this.createNumbersTable(database);
			TrackerProvider.this.createSettingsTable(database);
		}
		
		@Override
		public void onUpgrade(final SQLiteDatabase database, final int oldVersion, final int newVersion) {
			Log.w(LOG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", all old data will be destroyed!");
			
			database.execSQL("DROP TABLE IF EXISTS " + TrackerProviderSetup.Numbers.TABLE_NAME);
			database.execSQL("DROP TABLE IF EXISTS " + TrackerProviderSetup.Settings.TABLE_NAME);
			
			this.onCreate(database);
		}
	}
	
	@Override
	public boolean onCreate() {
		this.database = (new DatabaseHelper(this.getContext())).getWritableDatabase();
		return ((this.database == null) ? false : true);
	}
	
	@Override
	public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
		final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
		
		switch (TrackerProviderSetup.MATCHER.match(uri)) {
			case TrackerProviderSetup.Numbers.TABLE:
				builder.setTables(TrackerProviderSetup.Numbers.TABLE_NAME);
				builder.setProjectionMap(TrackerProviderSetup.Numbers.PROJECTION);
				break;
				
			case TrackerProviderSetup.Numbers.TABLE_NUMBER:
				builder.setTables(TrackerProviderSetup.Numbers.TABLE_NAME);
				builder.setProjectionMap(TrackerProviderSetup.Numbers.PROJECTION);
				builder.appendWhere(TrackerProviderSetup.Numbers.NUMBER + "='" + uri.getPathSegments().get(1) + "'");
				break;
				
			case TrackerProviderSetup.Settings.TABLE:
				builder.setTables(TrackerProviderSetup.Settings.TABLE_NAME);
				builder.setProjectionMap(TrackerProviderSetup.Settings.PROJECTION);
				break;
				
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		final Cursor cursor = builder.query(this.database, projection, selection, selectionArgs, null, null, sortOrder);
		cursor.setNotificationUri(this.getContext().getContentResolver(), uri);
		
		return cursor;
	}
	
	@Override
	public Uri insert(final Uri uri, final ContentValues initialValues) {
		ContentValues values;
		
		if (initialValues != null) {
			values = new ContentValues(initialValues);
		}
		else {
			values = new ContentValues();
		}
		
		long rowId;
		
		switch (TrackerProviderSetup.MATCHER.match(uri)) {
			case TrackerProviderSetup.Numbers.TABLE:
				rowId = this.database.insert(TrackerProviderSetup.Numbers.TABLE_NAME, TrackerProviderSetup.Numbers.getNullColumnHack(), values);
				if (rowId > 0) {
					final Uri newUri = ContentUris.withAppendedId(TrackerProviderSetup.Numbers.NUMBERS_URI, rowId);
					this.getContext().getContentResolver().notifyChange(newUri, null);
					return newUri;
				}
				
				break;
				
			case TrackerProviderSetup.Settings.TABLE:
				rowId = this.database.insert(TrackerProviderSetup.Settings.TABLE_NAME, TrackerProviderSetup.Settings.getNullColumnHack(), values);
				if (rowId > 0) {
					final Uri newUri = ContentUris.withAppendedId(TrackerProviderSetup.Settings.CONTENT_URI, rowId);
					this.getContext().getContentResolver().notifyChange(newUri, null);
					return newUri;
				}
				
				break;
				
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		throw new SQLException("Failed to insert row into " + uri);
	}
	
	@Override
	public int update(final Uri uri, final ContentValues values, final String where, final String[] whereArgs) {
		int count;
		
		switch (TrackerProviderSetup.MATCHER.match(uri)) {
			case TrackerProviderSetup.Numbers.TABLE:
				count = this.database.update(TrackerProviderSetup.Numbers.TABLE_NAME, values, where, whereArgs);
				break;
				
			case TrackerProviderSetup.Numbers.TABLE_NUMBER:
				count = this.database.update(TrackerProviderSetup.Numbers.TABLE_NAME, values, TrackerProviderSetup.getIdColumnName() + '=' + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
				break;
				
			case TrackerProviderSetup.Settings.TABLE:
				count = this.database.update(TrackerProviderSetup.Settings.TABLE_NAME, values, where, whereArgs);
				break;
				
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		this.getContext().getContentResolver().notifyChange(uri, null);
		
		return count;
	}
	
	@Override
	public int delete(final Uri uri, final String where, final String[] whereArgs) {
		int count;
		
		switch (TrackerProviderSetup.MATCHER.match(uri)) {
			case TrackerProviderSetup.Numbers.TABLE:
				count = this.database.delete(TrackerProviderSetup.Numbers.TABLE_NAME, where, whereArgs);
				break;
				
			case TrackerProviderSetup.Numbers.TABLE_NUMBER:
				count = this.database.delete(TrackerProviderSetup.Numbers.TABLE_NAME, TrackerProviderSetup.getIdColumnName() + '=' + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
				break;
				
			case TrackerProviderSetup.Settings.TABLE:
				count = this.database.delete(TrackerProviderSetup.Settings.TABLE_NAME, where, whereArgs);
				break;
				
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		this.getContext().getContentResolver().notifyChange(uri, null);
		
		return count;
	}
	
	@Override
	public String getType(final Uri uri) {
		return null;
	}
	
	private void createNumbersTable(final SQLiteDatabase database) {
		database.execSQL("CREATE TABLE " + TrackerProviderSetup.Numbers.TABLE_NAME + " (" + TrackerProviderSetup.getIdColumnName() + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + TrackerProviderSetup.Numbers.CARRIER + " INTEGER(2), " + TrackerProviderSetup.Numbers.NUMBER + " VARCHAR(50) NOT NULL);");
	}
	
	private void createSettingsTable(final SQLiteDatabase database) {
		final Cursor cursor = database.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='" + TrackerProviderSetup.Settings.TABLE_NAME + "'", null);
		
		try {
			if (cursor.getCount() == 0) {
				database.execSQL("CREATE TABLE " + TrackerProviderSetup.Settings.TABLE_NAME + " (" + TrackerProviderSetup.Settings.MAP_TYPE + " INTEGER(3));");
				
				final ContentValues values = new ContentValues();
				values.put(TrackerProviderSetup.Settings.MAP_TYPE, Settings.TYPE_MAP);
				
				database.insert(TrackerProviderSetup.Settings.TABLE_NAME, TrackerProviderSetup.Settings.getNullColumnHack(), values);
			}
		}
		finally {
			cursor.close();
		}
	}
	
}